package cn.edu.cqu.bysj.wm.gui;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.swing.ButtonGroup;
import javax.swing.ButtonModel;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JSpinner;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import mySwingToolkit.ui.ButtonTabComponent;

import org.neo4j.graphdb.Direction;
import org.pushingpixels.substance.api.SubstanceLookAndFeel;

import cn.edu.cqu.bysj.wm.ago.gn.GNRun;
import cn.edu.cqu.bysj.wm.ago.lp.LPRun;
import cn.edu.cqu.bysj.wm.def.ConstDef;
import cn.edu.cqu.bysj.wm.def.ConstDef.ConfigType;
import cn.edu.cqu.bysj.wm.def.Weight;
import cn.edu.cqu.bysj.wm.gui.component.AlgorithmTabPane;
import cn.edu.cqu.bysj.wm.gui.model.AlgorithmConfig;
import cn.edu.cqu.bysj.wm.gui.model.AlgorithmResult;
import cn.edu.cqu.bysj.wm.util.CommunityOutput;
import cn.edu.cqu.bysj.wm.util.ExportData;
import cn.edu.cqu.bysj.wm.util.KeyNodesOuput;

public class MainFrame {

	public static int TotalNumber = 0;
	private static final String RESET_COMMAND_TOOLKIT = "复位，重算社区发现";
	private static final String WEIGHT_COMMAND = "加权图";
	private static final String RESET_COMMAND = "复位";
	private static final String RUN_JD_ALG_COMMAND = "运行节点发现算法";
	private static final String RUN_SQ_ALG_COMMAND = "运行社区发现算法";
	public static final String JD = "JD";
	public static final String SQ = "SQ";
	private static final String PRINT_COMMAND = "打印结果到文本";
	private static final String HELP_COMMAND = "算法演示帮助";
	private static final String ABOUT_COMMAND = "关于";
	public JFrame frame;

	private JSplitPane splitPaneRight;

	private JTabbedPane tabbedPane;
	private DataFileTree sFileTree;

	AlgorithmConfig currentAlgorithmConfig;

	private JLabel selectedFile = new JLabel();
	private JButton clearButton = new JButton("重新计算");
	private ButtonGroup directionTypeButtonGroup;

	/**
	 * launch the application
	 */
	public static void main(String[] args) {
		
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					MainFrame window = new MainFrame();
					// defaultSkin(window);
					changeSkin(window.frame,
							"SubstanceOfficeSilver2007LookAndFeel");
					// windowSkin(window.frame);
					window.frame.setVisible(true);

				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * create the application
	 */
	public MainFrame() {
		initialize();
	}

	/**
	 * initialize the contents of the frame
	 */
	private void initialize() {
		frame = new JFrame();
		frame.setTitle("社区发现-关键节点算法演示");
		frame.addComponentListener(new ComponentAdapter() {
			@Override
			public void componentResized(ComponentEvent e) {
				splitPane.setDividerLocation(0.15);
				splitPaneRight.setDividerLocation(35);
			}
		});
		frame.setBounds(100, 100, 918, 575);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		this.initMenu();

		splitPane = new JSplitPane();
		splitPane.setDividerSize(3);
		frame.getContentPane().add(splitPane, BorderLayout.CENTER);

		splitPane.setLeftComponent(this.initLeft());

		splitPaneRight = new JSplitPane();
		splitPaneRight.setOrientation(JSplitPane.VERTICAL_SPLIT);
		splitPane.setRightComponent(splitPaneRight);
		splitPaneRight.setDividerSize(3);

		globalInfoPanel = new JPanel();
		splitPaneRight.setLeftComponent(globalInfoPanel);
		this.initRightTop();

		tabbedPane = new JTabbedPane(JTabbedPane.TOP);
		splitPaneRight.setRightComponent(tabbedPane);

		tabbedPane.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				JTabbedPane tabbedPane = (JTabbedPane) e.getSource();
				AlgorithmTabPane tabpane = (AlgorithmTabPane) tabbedPane
						.getSelectedComponent();
				updateGlobalInfo(tabpane.getResult(), tabpane.getConfigure()
						.getFilePath());
			}
		});

		JToolBar toolBar = new JToolBar();
		frame.getContentPane().add(toolBar, BorderLayout.NORTH);

		runSQButton = ImageButton.makeNavigationButton("run1.png",
				RUN_SQ_ALG_COMMAND, RUN_SQ_ALG_COMMAND, RUN_SQ_ALG_COMMAND,
				actionListener);
		toolBar.add(runSQButton);

		runJDButton = ImageButton.makeNavigationButton("run2.png",
				RUN_JD_ALG_COMMAND, RUN_JD_ALG_COMMAND, RUN_JD_ALG_COMMAND,
				actionListener);
		toolBar.add(runJDButton);

		resetButton = ImageButton.makeNavigationButton("reset.png",
				RESET_COMMAND, RESET_COMMAND_TOOLKIT, RESET_COMMAND_TOOLKIT,
				actionListener);
		toolBar.add(resetButton);

		printButton = ImageButton.makeNavigationButton("print.png",
				PRINT_COMMAND, PRINT_COMMAND, PRINT_COMMAND, actionListener);
		toolBar.add(printButton);

		helpButton = ImageButton.makeNavigationButton("help.png", HELP_COMMAND,
				HELP_COMMAND, HELP_COMMAND, actionListener);
		toolBar.add(helpButton);

		aboutButton = ImageButton.makeNavigationButton("about.png",
				ABOUT_COMMAND, ABOUT_COMMAND, ABOUT_COMMAND, actionListener);
		toolBar.add(aboutButton);

		JPanel panel = new JPanel();
		toolBar.add(panel);

		toggleButton = ImageToggleButton.makeNavigationToggleButton(
				"weight-off.png", "weight-on.png", WEIGHT_COMMAND,
				WEIGHT_COMMAND, WEIGHT_COMMAND, actionListener);
		panel.add(new JLabel("加权图"));
		panel.add(toggleButton);

		JLabel lblNewLabel = new JLabel("     ");
		panel.add(lblNewLabel);

		directionTypeButton1 = new JRadioButton(ConstDef.DIRECTION_DOUBLE);
		panel.add(directionTypeButton1);

		directionTypeButton2 = new JRadioButton(ConstDef.DIRECTION_INPUT);
		panel.add(directionTypeButton2);
		directionTypeButton3 = new JRadioButton(ConstDef.DIRECTION_OUTPUT);
		panel.add(directionTypeButton3);
		directionTypeButton1.setActionCommand(ConstDef.DIRECTION_DOUBLE);
		directionTypeButton2.setActionCommand(ConstDef.DIRECTION_INPUT);
		directionTypeButton3.setActionCommand(ConstDef.DIRECTION_OUTPUT);

		directionTypeButtonGroup = new ButtonGroup();
		directionTypeButtonGroup.add(directionTypeButton3);
		directionTypeButtonGroup.add(directionTypeButton2);
		directionTypeButtonGroup.add(directionTypeButton1);

		JLabel label_1 = new JLabel("     ");
		panel.add(label_1);

		JLabel label = new JLabel("运行次数");
		panel.add(label);

		runTime = new JSpinner();
		runTime.setModel(new SpinnerNumberModel(1, 1, 20, 1));
		panel.add(runTime);

		prepareSQ();
		frame.setExtendedState(javax.swing.JFrame.MAXIMIZED_BOTH);// 设置窗口最大化
		System.err.close();
	}

	/**
	 * @param configure
	 */
	protected void updateGlobalInfo(AlgorithmResult result, String filePath) {

		getNodeNumber().setText(result.getNodesNumber() + "");
		getEdgeNumber().setText(result.getEdgesNumber() + "");
		getSelectedFile().setText(filePath);
	}

	/**
	 * initialize menu bar
	 */
	private void initMenu() {
		JMenuBar menuBar = new JMenuBar();

		JMenu mnNewMenu = new JMenu("New menu");
		menuBar.add(mnNewMenu);

		JMenu mnNewMenu_2 = new JMenu("New menu");
		mnNewMenu.add(mnNewMenu_2);

		JMenuItem mntmNewMenuItem_1 = new JMenuItem("New menu item");
		mnNewMenu_2.add(mntmNewMenuItem_1);

		JMenuItem mntmNewMenuItem = new JMenuItem("New menu item");
		mnNewMenu_2.add(mntmNewMenuItem);

		JMenuItem mntmNewMenuItem_2 = new JMenuItem("New menu item");
		mnNewMenu.add(mntmNewMenuItem_2);

		JMenu mnNewMenu_1 = new JMenu("New menu");
		menuBar.add(mnNewMenu_1);
	}

	/**
	 * initialize file tree
	 * 
	 * @return
	 */
	private JPanel initLeft() {
		sFileTree = new DataFileTree("data/", getSelectedFile(), clearButton);
		JPanel panel = new JPanel();
		panel.setLayout(new BorderLayout(0, 0));
		panel.add(sFileTree.getComponent(), BorderLayout.CENTER);
		JLabel label = new JLabel("文件列表");
		panel.add(label, BorderLayout.NORTH);
		return panel;
	}

	/**
	 * initialize info on right top
	 */
	private void initRightTop() {

		JLabel nodeNumberLabel = new JLabel("节点数");
		globalInfoPanel.add(nodeNumberLabel);

		setNodeNumber(new JLabel("0"));
		globalInfoPanel.add(getNodeNumber());

		JLabel white1lb = new JLabel("      ");
		globalInfoPanel.add(white1lb);

		JLabel edgeNumberLabel = new JLabel("边数");
		globalInfoPanel.add(edgeNumberLabel);

		setEdgeNumber(new JLabel("0"));
		globalInfoPanel.add(getEdgeNumber());

		JLabel white2lb = new JLabel("      ");
		globalInfoPanel.add(white2lb);

		JLabel selectedFileLabel = new JLabel("所选文件");
		globalInfoPanel.add(selectedFileLabel);
		globalInfoPanel.add(getSelectedFile());

	}

	/**
	 * change skin
	 * 
	 * @param frame
	 * @param cmd
	 */
	private static void changeSkin(JFrame frame, String cmd) {
		if (cmd.startsWith("Substance")) {
			cmd = "org.pushingpixels.substance.api.skin." + cmd;
			try {
				SubstanceLookAndFeel slf = (SubstanceLookAndFeel) Class
						.forName(cmd).newInstance();
				System.out.println(slf);
				UIManager.setLookAndFeel(slf);
				SwingUtilities.updateComponentTreeUI(frame);
			} catch (ClassNotFoundException e1) {
				e1.printStackTrace();
			} catch (InstantiationException e2) {
				e2.printStackTrace();
			} catch (IllegalAccessException e3) {
				e3.printStackTrace();
			} catch (UnsupportedLookAndFeelException e4) {
				e4.printStackTrace();
			}
		} else {
			try {
				UIManager.setLookAndFeel(cmd);
			} catch (ClassNotFoundException e1) {
				e1.printStackTrace();
			} catch (InstantiationException e1) {
				e1.printStackTrace();
			} catch (IllegalAccessException e1) {
				e1.printStackTrace();
			} catch (UnsupportedLookAndFeelException e1) {
				e1.printStackTrace();
			}
			SwingUtilities.updateComponentTreeUI(frame);
		}
	}

	/**
	 * add tab to a detection result
	 * 
	 * @param title
	 * @param jp
	 */
	public void addTab(String title, Component jp) {
		tabbedPane.add(title, jp);
		tabbedPane.setTabComponentAt(tabbedPane.indexOfComponent(jp),
				new ButtonTabComponent(tabbedPane));
		tabbedPane.setSelectedComponent(jp);
	}

	/**
	 * open config dialog
	 */
	void openConfigUI() {
		ConfigUi dialog = null;
		if (currentAlgorithmConfig.getType().equals(ConfigType.JD)) {
			dialog = new JDConfigUI(this, true, currentAlgorithmConfig);

		} else {
			ButtonModel bm = null;
			if (selectedFile.getText() == null
					|| selectedFile.getText().equals("")) {
				JOptionPane.showMessageDialog(frame, "请从左侧文件树选择数据文件");
				return;
			}
			currentAlgorithmConfig.setFielPath(this.selectedFile.getText());

			bm = directionTypeButtonGroup.getSelection();
			if (bm == null) {
				JOptionPane.showMessageDialog(frame,
						"请选择传播方向 ：\n\t无向图：双向传播\n\t有向图:出度传播、入度传播");
				return;
			}
			currentAlgorithmConfig.setTime((Integer) runTime.getValue());
			currentAlgorithmConfig.setDirection(getDirectionType(bm
					.getActionCommand()));
			dialog = new SQConfigUI(this, true, currentAlgorithmConfig);
		}
		dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
		dialog.setVisible(true);
		System.out.println(dialog);
	}

	/**
	 * reset config
	 */
	private void resetCurrentConfig() {

		currentAlgorithmConfig = new AlgorithmConfig(TotalNumber++);
	}

	/**
	 * get derection
	 * 
	 * @param type
	 * @return
	 */
	private Direction getDirectionType(String type) {
		if (type.equals(ConstDef.DIRECTION_DOUBLE)) {
			return Direction.BOTH;
		} else if (type.equals(ConstDef.DIRECTION_INPUT)) {
			return Direction.INCOMING;
		} else if (type.equals(ConstDef.DIRECTION_OUTPUT)) {
			return Direction.OUTGOING;
		} else
			return null;
	}

	/**
	 * event to do after click the button on menu bar
	 */
	private ActionListener actionListener = new ActionListener() {
		@Override
		public void actionPerformed(ActionEvent e) {
			String cmd = e.getActionCommand();
			// Handle each button
			if (RUN_SQ_ALG_COMMAND.equals(cmd)) { // first button clicked
				openConfigUI();
			} else if (RUN_JD_ALG_COMMAND.equals(cmd)) { // second button
															// clicked
				openConfigUI();
			} else if (RESET_COMMAND.equals(cmd)) {
				prepareSQ();
			} else if (WEIGHT_COMMAND.equals(cmd)) {
				if (((JToggleButton) e.getSource()).isSelected()) {
					currentAlgorithmConfig.setWeight(Weight.WEIGHTED);
				}
			} else if (PRINT_COMMAND.equals(cmd)) {
				SimpleDateFormat sdf = new SimpleDateFormat(
						"yyyy-MM-dd-hh-mm-ss");
				String path = ConstDef.OUTPUT_FILE + sdf.format(new Date())
						+ ".txt";
				ExportData.exportData(CommunityOutput.printBuilder.toString()
						.replaceAll("\n", "\r\n"), path);
				try {
					Runtime.getRuntime().exec(
							new String[] { "notepad.exe", path });
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				CommunityOutput.initPrintBuilder();
				KeyNodesOuput.setPrintBuilder();
			} else if (HELP_COMMAND.equals(cmd)) {
				new HelpDialog();
			} else if (ABOUT_COMMAND.equals(cmd)) {
				new AboutDialog();
			}
		}
	};
	private JButton runSQButton;
	private JButton runJDButton;
	private JButton resetButton;
	private JButton printButton;
	private JButton helpButton;
	private JButton aboutButton;

	private JToggleButton toggleButton;
	private JRadioButton directionTypeButton2;
	private JRadioButton directionTypeButton3;
	private JRadioButton directionTypeButton1;
	private JPanel globalInfoPanel;
	private JSpinner runTime;
	private JSplitPane splitPane;
	private JLabel nodeNumber;
	private JLabel edgeNumber;

	/**
	 * prepare for key node detection
	 */
	public void prepareJD() {
		runSQButton.setEnabled(false);
		resetButton.setEnabled(true);
		if (currentAlgorithmConfig.getAlgorithmType().equals(
				ConstDef.AlgorithmType.GN)) {
			runJDButton.setEnabled(false);
		} else {
			runJDButton.setEnabled(true);
		}
		toggleButton.setEnabled(false);
		directionTypeButton1.setEnabled(false);
		directionTypeButton2.setEnabled(false);
		directionTypeButton3.setEnabled(false);
		runTime.setEnabled(false);
		sFileTree.setEnable(false);
		currentAlgorithmConfig.next();
	}

	/**
	 * prepare for community detection
	 */
	public void prepareSQ() {
		if (currentAlgorithmConfig != null) {
			if (currentAlgorithmConfig.getAlgorithmType().equals(
					ConstDef.AlgorithmType.GN)) {
				GNRun.closeDbService();
			} else {
				LPRun.closeDbService();
			}
		}
		this.nodeNumber.setText("0");
		this.edgeNumber.setText("0");
		resetCurrentConfig();
		runSQButton.setEnabled(true);
		runJDButton.setEnabled(false);
		resetButton.setEnabled(false);
		toggleButton.setEnabled(true);
		directionTypeButton1.setEnabled(true);
		directionTypeButton2.setEnabled(true);
		directionTypeButton3.setEnabled(true);
		directionTypeButton1.setSelected(true);
		runTime.setEnabled(true);
		sFileTree.setEnable(true);

	}

	public JLabel getSelectedFile() {
		return selectedFile;
	}

	public void setSelectedFile(JLabel selectedFile) {
		this.selectedFile = selectedFile;
	}

	public JLabel getNodeNumber() {
		return nodeNumber;
	}

	public void setNodeNumber(JLabel nodeNumber) {
		this.nodeNumber = nodeNumber;
	}

	public JLabel getEdgeNumber() {
		return edgeNumber;
	}

	public void setEdgeNumber(JLabel edgeNumber) {
		this.edgeNumber = edgeNumber;
	}
}
